/**
 * gridTemplate 是一款基于jQuery开发的表格（含分页）套件。
 * 提供非常灵活的前端表格开发模板方法工具。
 * 使用配置灵活，分页样式灵活，便于扩展。
 * gridTemplate + JS模板引擎是最好的搭配。
 * 前端开发者不用关心前段表格加载、分页等基础问题，仅需要关心如何结合JS模板引擎来渲染自己的表格，表格样式由自己自由发挥。
 * 不在受限于传统的表格前端工具。样式有你定。
 * 使用方法有两种：
 * 1.本地方法调用：
       gridTemplate($("div.gridContainer"),{
	                 ajax:{url:"xx"},
	                 render:function(data,container){
                  });
   2.jQuery调用（推荐）:
        $("div.gridContainer").gridTemplate({
	                 ajax:{url:"xx"},
	                 render:function(data,container){
                   });
                   
 * @author jsonzou(keko-boy@163.com)
 */
(function($){
	/**
	 * 表格管理器
	 */
   var GridTemplateManager={
		  /**
		   * 配置项，调用时配置相关参数
		   */
		  option:{
			ajax:{ // jQuery.ajax 通用参数 
				url:null, // 必填。
				data:{},
				dataType:'json',
				async:true,
				type:'post',
				beforeSend:null,
				success:null,
				error:null
			},
			pagination:{ // 分页参数
				enabled:true, // 是否启用分页[true,false]，默认true,设为false后一下参数失效
				style:'pagination_default',// 分页样式
				//pageList:[10,20,50,100], // 暂不支持，觉得输入pageSize最灵活且好用
				pageSize:10, // 每页记录数
				page:1, // 页码
				buttons:{ // 分页按钮设置
					     first:1, // 首页按钮； 大于等于1则显示，小于1则不显示，默认1.
					     pre:1, // 上一页按钮； 大于等于1则显示，小于1则不显示，默认1.
					     num:5, // 数字页码按钮； 大于等于1则显示，小于1则不显示，大于0表示按钮页码最多出现的数量，默认5.
					     next:1, // 下一页按钮； 大于等于1则显示，小于1则不显示，默认1.
					     last:1 // 未页按钮； 大于等于1则显示，小于1则不显示，默认1.
				    }
			},
			dataNames:{ // 自定义数据属性名称
		    	 page:'page', // 分页参数名称
		    	 pageSize:'pageSize', // 每页记录大小参数名称
		    	 total:'total', // 记录总数属性名称
		    	 rows:'rows' // 行记录数组属性名称
		    }, 
		    /**
			 * 配置话术信息
			 */
			messages:{ 
				totalPrefix:"共",
				totalSubfix:"条记录",
				pageSizePrefix:"显示",
				pageSizeSubfix:"条/页",
				firstPage:"首页",
				prePage:"上一页",
				nextPage:"下一页",
				lastPage:"末页"
			},
			
		    fitGridData:null, // 适配数据接口。有时候后台返回的数据不是我们直接就能去得的，需要在此适配。参数列表[data]
			beforeRender:null, // 装载数据表格前调用接口;参数列表[data,container]
			render:null,//必填。 装载数据表格时调用接口;本插件把数据的渲染主动权交给开发者，可以自定决定如何显示表格，在此可以借助已经很成熟的JS模板引擎插件。参数列表[data,container]
			afterRender:null // 装载数据表格后调用接口;参数列表[data,container]
		},
		/**
		 * 分页结构HTML模板
		 */
		pageHtmlTemplate:["<div class='pagelist'>", 
					      "  <div class='page_size'>",
					      "  </div>",
					      "  <div class='page_content'>",
						  "  </div>",
			              " </div>"].join(""),
       /**
        * 表格容器
        */			              
		container:null,
		/**
		 * 初始化
		 */
	    init:function(container,option){
		   var that=this;
		   that.setOption(option);
		   that.container=container;
		   var gridContainer=$("<div _grid_part='grid'></div>");
		   that.container.append(gridContainer);
		   if(that.option.pagination.enabled){
			   var pageContainer=$("<div _grid_part='page'></div>");
			   pageContainer.addClass(that.option.pagination.style || 'pagination_default'); 
			   that.container.append(pageContainer);
		   }
		   that.loadData();
		},
		/**
		 * 加载表格
		 */
		loadData:function(){
			var that=this;
			var params=that.option.ajax.data||{};
			if(that.option.pagination.enabled){
				params[that.option.dataNames['page']]= that.option.pagination.page || 1;
				params[that.option.dataNames['pageSize']]=that.option.pagination.pageSize || 10;
			}
			$.ajax({
				  url: that.option.ajax.url,
				  data:params,
				  cache:false,
				  beforeSend:function(){
					  that._beforeSend();
				  },
				  success:function(data){
					  that._success(data);
					  
					  var _dta=that._fitGridData(data);
					  
					  var gridPart= that.container.find("[_grid_part='grid']");
					  that._beforeRender(_dta,gridPart);
					  
					  //that.container.html(template(that.tempId,_dta));
					  that._render(_dta,gridPart);
					  
					  that._afterRender(_dta,gridPart);
					  
					  var pagePart= that.container.find("[_grid_part='page']");
					  that.pagination(_dta,pagePart);
				  },
				  error:function(res){
					  that._error(res);
				  }
				  
			  });
		},
		/**
		 * 
		 * 合并设置配置项
		 * @param option
		 */
		setOption:function(option){
			var that=this;
			that.option=$.extend(true,{},that.option,option);
		},
		/**
		 * 重新加载，配置项可以自定义，比如将页码从1开始等
		 * @param option 配置项
		 */
		reload:function(option){
			var that=this;
		    that.setOption(option);
		    that.loadData();
		},
		/**
		 * 分页插件
		 * @param _dta 数据
		 * @param container 容器
		 */
		pagination:function(_dta,container){
			var that=this;
			
			if(!that.option.pagination.enabled&&container.length>0){
				return ;
			}
			var pageTool=container.find(".pagelist");
			var rowTotal=_dta[that.option.dataNames['total']];
			var buttons=that.option.pagination.buttons;
			 
			var pageTotal=rowTotal%that.option.pagination.pageSize>0?
					      Math.ceil(rowTotal/that.option.pagination.pageSize):
						  Math.floor(rowTotal/that.option.pagination.pageSize);
			// 分页管理器
			var pageManager={ 
					numPage:{
						first:1,
						last:buttons.num<pageTotal?buttons.num:pageTotal,
						same:"+"
					},
					first:function(container){
						var pageThat=this;
						that.option.pagination.page=1;
						pageThat._pageStyle(container);
						
						that.loadData();
					},
					pre:function(container){
						var pageThat=this;
						if(that.option.pagination.page>1){
							that.option.pagination.page-=1;
							
							pageThat._pageStyle(container);
							
							that.loadData();
						}
					},
					num:function(container,pagebtn){
						var pageThat=this;
						if(pageThat.numPage.first==pageThat.numPage.last){
							if(pageThat.numPage.same=='+'){
								pageThat.next(container);
							}else if(pageThat.numPage.same=='-'){
								pageThat.pre(container);
							}
						}else{
							 that.option.pagination.page=pagebtn.text()*1;
							 pageThat._pageStyle(container);
							 that.loadData();
						}
						
						
					},
					next:function(container){
						var pageThat=this;
						if(that.option.pagination.page<pageTotal){
							that.option.pagination.page+=1;
							pageThat._pageStyle(container);
							
							that.loadData();
						}
					},
					last:function(container){
						var pageThat=this;
						that.option.pagination.page=pageTotal;
						
						pageThat._pageStyle(container);
						
						that.loadData();
					},
					_pageStyle:function(container){
						var pageThat=this;
						container.find("button[page]").removeClass("disabled");
						
						if(that.option.pagination.page<=1){
							// todo设置上一页、首页为disabled
							container.find("button[page='first'],button[page='pre']").addClass("disabled");
					    }
					 
					    if(that.option.pagination.page>=pageTotal){
							// todo设置下一页、末页为disabled
					    	container.find("button[page='next'],button[page='last']").addClass("disabled");
					    }
					    
					    if(buttons.num>0){ // 计算数字数码
					    	var helfNum=Math.ceil(buttons.num/2);
					        var numBtns=pageTool.find("[page='nums']");
					        var isRefresh=false;
					        if(buttons.num==1&&pageThat.numPage.first==pageThat.numPage.last){
					        	if(pageThat.numPage.same=='+'&&pageThat.numPage.last<pageTotal){
					        		pageThat.numPage.first+=1;
						    		pageThat.numPage.last=pageThat.numPage.first;
						    		if(pageThat.numPage.last==pageTotal){
						    			pageThat.numPage.same="-";
						    		}
					        	}else if(pageThat.numPage.same=='-'&&pageThat.numPage.last>1){
					        		pageThat.numPage.first-=1;
					        		if(pageThat.numPage.first<=0){
						    			pageThat.numPage.first=1;
						    		}
						    		pageThat.numPage.last=pageThat.numPage.first;
					        		if(pageThat.numPage.last==1){
						    			pageThat.numPage.same="+";
						    		}
					        	}
					    		
					    		isRefresh=true;
					    	}else if(that.option.pagination.page-pageThat.numPage.first>=helfNum&&pageThat.numPage.last<=pageTotal){
					    		pageThat.numPage.last=that.option.pagination.page+helfNum<pageTotal?that.option.pagination.page+helfNum-1:pageTotal;
					    		pageThat.numPage.first=pageThat.numPage.last-buttons.num+1;
					    		if(pageThat.numPage.first<=0){
					    			pageThat.numPage.first=1;
					    		}
					    		isRefresh=true;
					    	}else if(that.option.pagination.page-pageThat.numPage.first<helfNum&&pageThat.numPage.first>1){
					    	 
					    		pageThat.numPage.first=that.option.pagination.page-helfNum>=1?that.option.pagination.page-helfNum:1;
					    		pageThat.numPage.last=pageThat.numPage.first+buttons.num-1;
					    		if(pageThat.numPage.first<=0){
					    			pageThat.numPage.first=1;
					    		}
					    		isRefresh=true;
					    	}
					    	
					    	 if(isRefresh){
					    		 numBtns.empty();
					    		 for(var i=pageThat.numPage.first;i<=pageThat.numPage.last;i++){
										var val=i;
										var btn=$(["<button type='button' page='num'>",val,"</button>"].join(""));
										btn.attr("val",val);
										numBtns.append(btn);
								 }
					    	 }
					    	 
					    	 
					    	 // 设置页码样式
						    	var pageNumButtonsJqArr= numBtns.find("button");
						    	pageNumButtonsJqArr.removeClass("current");
						    	pageNumButtonsJqArr.filter("[val='"+that.option.pagination.page+"']").addClass("current");
					    	 
					    }
					    
					}
			};
			// 分页工具栏
			if(pageTool.length==0 // 分页工具不存在
			   || container.attr("rowTotal")!=rowTotal // 或者总数发生变化
			   || container.attr("pageTotal")!=pageTotal){ // 或者分页发生变化
				if(pageTool.length>0){
					pageTool.remove();
				}
				container.attr("rowTotal",rowTotal);
				container.attr("pageTotal",pageTotal);
				
				pageTool=$(that.pageHtmlTemplate);
				container.append(pageTool);
				var pageSize=pageTool.find(".page_size");
				pageSize.empty();
				pageSize.html([
				              "<span page='total' class='total'>",that.option.messages['totalPrefix'],
				               "<span  class='totalnum'>" ,rowTotal,"</span>",
				              that.option.messages['totalSubfix'],"</span>",
				              "<span>",that.option.messages['pageSizePrefix'],"</span>",
						      "<input page='pageSize' type='text' value='",that.option.pagination.pageSize,"' class='pagenum' />",
						      "<span>",that.option.messages['pageSizeSubfix'],"</span>"].join(""));
				
				var pageButtons=pageTool.find(".page_content");
				pageButtons.empty();
				
				
				if(buttons.first>=1){
					pageButtons.append(["<button type='button' page='first'>",that.option.messages['firstPage'],"</button>"].join(""));
				}
				
				if(buttons.pre>=1){
					pageButtons.append(["<button type='button' page='pre'>",that.option.messages['prePage'],"</button>"].join(""));
				}
				
				if(buttons.num>0){
					var numBtns=$("<span page='nums'></span>");
					pageButtons.append(numBtns);
					for(var i=0;i<(pageTotal>buttons.num?buttons.num:pageTotal);i++){
						var val=pageManager.numPage.first+i;
						 
						var btn=$(["<button type='button' page='num'>",val,"</button>"].join(""));
						btn.attr("val",val);
						numBtns.append(btn);
					}
				}
				
				if(buttons.next>=1){
					pageButtons.append(["<button type='button' page='next'>",that.option.messages['nextPage'],"</button>"].join(""));
				}
				
				if(buttons.last>=1){
					pageButtons.append(["<button type='button' page='last'>",that.option.messages['lastPage'],"</button>"].join(""));
				}
				
				pageManager._pageStyle(container);// 样式
				 
				// 绑定页数大小事件
				that.container.off("keyup.page");
				that.container.on("keyup.page","[page='pageSize']",function(event){
					if(event.keyCode=='13'){
						 that.option.pagination.pageSize=$(this).val()*1;
						 that.option.pagination.page=1;
						 that.loadData();
					}
				});
				
				// 绑定分页按钮事件
				that.container.off("click.page");
				that.container.on("click.page","[page]",function(key){
					var action=$(this).attr("page");
					 if(pageManager[action]){
						 pageManager[action].call(pageManager,container,$(this));
					 }
				});
				 
			     
				 
			}
			
		},
		/**
		 *  
		 * @param data 
		 * @returns
		 */
		_success:function(data){
			var that=this;
			return that._exec('success',that.option.ajax,data);
		},
		_error:function(res){
			var that=this;
			return that._exec('error',that.option.ajax,res);
		},
		_beforeSend:function(){
			var that=this;
			return that._exec('beforeSend',that.option.ajax);
		},
		_beforeRender:function(_dta,container){
			var that=this;
			return that._exec('beforeRender',that.option,_dta,container);
		},
		_render:function(_dta,container){
			 var that=this;
			 return that._exec('render',that.option,_dta,container);
		},
		_afterRender:function(_dta,container){
			 var that=this;
			 return that._exec('afterRender',that.option,_dta,container);
		},
		_fitGridData:function(data){
		    var that=this;
		    return that._exec('fitGridData',that.option,data);
		},
		_exec:function(func,conf,data,container){
			var that=this;
			if(conf[func]){
				return conf[func].call(that,data,container);
			}else{
				return data;
			}
		}
	};
	/**
	 * 可以直接顶级变量调用：gridTemplate($("div.gridContainer"),{ajax:{..}});
	 */
	window.gridTemplate=function(container,option){
		GridTemplateManager.init(container,option);
		return {
			reload:function(option){
				GridTemplateManager.reload(option);
			},
			setOption:function(option){
				GridTemplateManager.setOption(option);
			}
		};
	};
	
	/**
	 * jQuery扩展插件，调用：$("div.gridContainer").gridTemplate({ajax:{..}});
	 */
	$.fn.extend({
		gridTemplate:function(option){
			return gridTemplate($(this),option);
		}
	});
	
	
})(jQuery);
